package com.juku2024.juku.viewmodel

import android.app.Activity
import android.text.TextUtils
import androidx.lifecycle.viewModelScope
import com.blankj.utilcode.util.FileUtils
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.wanban.adutils.callback.OnLoadAdCallback
import com.wanban.adutils.db.AdRoomUtils
import com.wanban.adutils.tools.AdConstants
import com.wanban.adutils.utils.CommonAdTools
import com.juku2024.juku.BuildConfig
import com.juku2024.juku.R
import com.juku2024.juku.base.BaseApplication
import com.juku2024.juku.db.NoteRoomUtils
import com.juku2024.juku.db.entity.FavoriteEntity
import com.juku2024.juku.db.entity.HistoryEntity
import com.juku2024.juku.db.entity.VideoEntity
import com.juku2024.juku.db.entity.VideoEpisodeEntity
import com.juku2024.juku.db.entity.VideoPlayHistoryEntity
import com.juku2024.juku.db.entity.VideoRecommendModel
import com.juku2024.juku.model.CommonResponse
import com.juku2024.juku.model.EpisodesResponse
import com.juku2024.juku.model.PartVideoDetailResponse
import com.juku2024.juku.model.PlayInfoResponse
import com.juku2024.juku.network.api.Api
import com.juku2024.juku.network.retrofit.OnRetrofitResultListener
import com.juku2024.juku.network.retrofit.RetrofitUtils
import com.juku2024.juku.request.VideoDetailRequest
import com.juku2024.juku.request.VideoRecommendRequest
import com.juku2024.juku.tools.AppUtils
import com.juku2024.juku.tools.Constants
import com.juku2024.juku.tools.EncryptionUtils
import com.juku2024.juku.tools.MD5Utils
import com.juku2024.juku.tools.SPUtil
import com.wanban.download.db.DatabaseUtils
import com.wanban.download.db.DownloadEntity
import com.wanban.download.db.DownloadSQLiteHelper
import com.wanban.download.model.Status
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File

class VideoDetailViewModelNew : BaseViewModel() {

    // 剧集列表排序，是否反转
    var isEpisodeReverse = false
    // 当前的视频源
    var currentSourceId = 0
    // 当前的剧集位置
    var currentEpisodePosition = 0
    // 当前的播放位置
    var currentPlayStartPosition = 0L
    // 是否配置了解锁广告
    var isSetLockVideoAd = false
    var videoDetailModel: VideoEntity? = null

    private var videoPlayHistoryEntity: VideoPlayHistoryEntity? = null


    /** 获取商品详情 */
    fun getVideoDetail(videoId: Long, callback: OnRetrofitResultListener<VideoEntity>) {
        viewModelScope.launch {
            try {
                // 获取视频版本号
                var videoModel = withContext(Dispatchers.IO) {
                    val result = NoteRoomUtils.getInstance().videoEntityDao().query(videoId)
                    if (!TextUtils.isEmpty(result?.sourceFilePath)) {
                        val file = File(result.sourceFilePath)
                        if (FileUtils.isFileExists(file)) {
                            val playInfoStr = file.readText()
                            if (!TextUtils.isEmpty(playInfoStr)) {
                                // 格式化数据
                                val listType = object : TypeToken<ArrayList<PlayInfoResponse>>() {}.type
                                val gson = Gson()
                                result.sourcePlayList = gson.fromJson(playInfoStr, listType) as ArrayList<PlayInfoResponse>
                            }
                        }
                    }
                    return@withContext result
                }
                // 更新本地视频缓存
                videoModel = if (videoModel == null || videoModel.version == "0" || videoModel.sourcePlayList.isNullOrEmpty()) { // 没有本地数据,
                        // 需要获取视频全部内容, 直接执行 ->
                        // params:{"id":8993,"appId":100010001,"timestamp":1629256693,"sign":"82fba6974b3cb36535cba3f8d156edc4"}
                        getFullVideoDetail(videoId)
                    } else { // 有本地缓存, 看是否需要更新
                        // params:{"id":8993,"version":5,"appId":100010001,"timestamp":1629256693,"sign":"f2812144ed9a0e985171fc6853643427"}
                        getVideoDetailPart(videoModel)
                    }
                if (videoModel == null) {
                    callback.onFailed(AppUtils.getString(R.string.error_net))
                    return@launch
                }

                if (videoModel.code == 444) { // 用户token失效
                    val tokenResult = updateToken()
                    if (!isActive) return@launch
                    if (tokenResult.code != 0) {
                        callback.onFailed(tokenResult.msg?:"验证信息失败，请检查您的网络链接！")
                        return@launch
                    }
                    getVideoDetail(videoId, callback)
                    return@launch
                }
                // 检查是否有可播放的内容
                if (videoModel.sourcePlayList.isNullOrEmpty()) {
                    callback.onFailed("1001")
                    return@launch
                }
                if (videoModel.sourcePlayList?.all { it.episodes.isNullOrEmpty() } == true) {
                    callback.onFailed("1001")
                    return@launch
                }

                // 处理视频线路
                // 线路排序要求
                // 1.置顶线路weight=9999
                // 2.推荐线路按weight排序
                // 3.剩余线路按${SPUtil.instance.videoSourceOrder}排序
                sortSourceByWeight(videoModel)

                currentSourceId = videoModel.sourcePlayList?.firstOrNull()?.id?:0

                // 处理历史播放，根据修改时间，倒序获取剧集播放记录，第一个默认就是上次最后播放的剧集信息
                videoPlayHistoryEntity = withContext(Dispatchers.IO) { NoteRoomUtils.getInstance().videoPlayDao().query(videoId) }
                if (videoPlayHistoryEntity == null || videoPlayHistoryEntity?.episodeList.isNullOrEmpty()) { // 没有播放历史
                    currentEpisodePosition = 0
                    currentPlayStartPosition = 0
                } else { // 有播放历史
                    val lastPlayEntity: VideoEpisodeEntity? = videoPlayHistoryEntity?.episodeList?.maxBy { it.updateTime }
                    if (lastPlayEntity == null) {
                        currentEpisodePosition = 0
                        currentPlayStartPosition = 0
                    } else {
                        currentSourceId = lastPlayEntity.sourceId
                        currentEpisodePosition = lastPlayEntity.episode
                        currentPlayStartPosition = lastPlayEntity.startPosition
                    }
                }

                // 处理剧集列表播放信息
                if (BuildConfig.DEBUG) {
                    videoModel.lockEps = 5
                }
                // 处理剧集列表相关操作
                dealWithVideoEpisodeInfo(videoModel)

                // 收藏
                val favorite = withContext(Dispatchers.IO) { NoteRoomUtils.getInstance().favoriteDao().queryFavorite(videoId)}
                videoModel.isFavorite = favorite != null

                this@VideoDetailViewModelNew.videoDetailModel = videoModel
                callback.onSuccess(videoModel)
            } catch (e: Exception) {
                e.printStackTrace()
                callback.onFailed(AppUtils.getString(R.string.error_net))
            }
        }
    }

    fun sortSourceByWeight(videoModel: VideoEntity) {
        // 如果让客户端排序，则需要按照剧集数多少排序
        if (SPUtil.instance.videoSourceOrder) {
            videoModel.sourcePlayList?.sortByDescending {
                return@sortByDescending it.episodes?.size ?: 0
            }
        }
        // 先给所有线路赋值初始weight，从头到尾，以此递减
        val sourceCount = videoModel.sourcePlayList?.size ?: 0
        videoModel.sourcePlayList?.forEachIndexed { index, playInfoResponse ->
            playInfoResponse.weight = sourceCount - index
        }

        // 按照解析线路中的weight设置到线路中
        val homeModel = NoteRoomUtils.getInstance().homeTabDao().query()
        homeModel?.analysis?.filter { it.weight > 0 }?.forEach { parseSourceModel ->
            val targetSource = videoModel.sourcePlayList?.firstOrNull { it.id == parseSourceModel.sourceId }
            if (targetSource != null) {
                targetSource.weight = parseSourceModel.weight
                targetSource.isRecommend = true
            }
        }

        // 设置置顶线路的weight
        val topSourceId = SPUtil.instance.defaultTopSource
        if (topSourceId >= 0) {
            val topSourceModel = videoModel.sourcePlayList?.firstOrNull { it.id == topSourceId }
            if (topSourceModel != null) {
                topSourceModel.weight = 9999
            }
        }
        videoModel.sourcePlayList?.sortByDescending { it.weight }
    }

    /**
     * 处理视频剧集列表相关信息
     * 主要是对剧集item新增一些后面使用的信息，包括视频id，去除无用数据，当前正在播放的标签，解锁广告标签等
     */
    private suspend fun dealWithVideoEpisodeInfo(videoModel: VideoEntity) = withContext(Dispatchers.IO) {
        val sourceList = videoModel.sourcePlayList ?: return@withContext
        // 检查是否有解锁广告
        isSetLockVideoAd = isSetLockVideoAd(videoModel.lockEps)
        // 当前所有剧集列表中剧集数最大值，用来判断
        val maxEpisodeCount = videoModel.sourcePlayList?.maxBy { it.episodes.size }?.episodes?.size ?: 0
        // 无用的剧集列表，主要是剧集列表可能为null或empty的线路
        val emptySource = ArrayList<PlayInfoResponse>()
        // 设置需要播放广告的
        for (playInfo in sourceList) {
            val episodeList = playInfo.episodes ?: continue
            val episodeCount = episodeList.size
            if (episodeCount <= 0) { // 无用的线路
                emptySource.add(playInfo)
                continue
            }
            // 先清空线路下载状态
            playInfo.hasDownloads = false
            // 根据当前的sourceId，videoId, episode 获取对应的下载对象
            for (episodeIndex in 0 until episodeCount) {
                val episodesResponse = episodeList[episodeIndex]
                episodesResponse.videoId = videoModel.id
                // 剧集播放信息，判断是否播放过
                val episodePlayInfo = videoPlayHistoryEntity?.episodeList?.firstOrNull { it.episode == episodeIndex }
                episodesResponse.isPlayed = episodePlayInfo != null
                // 视频分类
                episodesResponse.category = videoModel.category
                // 设置观看标签
                episodesResponse.isPlaying = episodeIndex == currentEpisodePosition
                episodesResponse.isDownloading = false
                playInfo.hasDownloads = false
                episodesResponse.status = Status.IDLE
                episodesResponse.isDownloaded = false
                // 设置播放器用的标题和解锁广告
                when (videoModel.category) {
                    Constants.VIDEO_CATEGORY_ALBUM -> {
                        // 设置剧集标题
                        episodesResponse.videoTitle = String.format("%s  第%s集", videoModel.name, episodesResponse.title)
                        // 第一个显示解锁广告的位置
                        val firstUnlockEpisodeIndex = maxEpisodeCount - videoModel.lockEps
                        // 设置解锁的条件
                        // 1.isSetLockVideoAd = true
                        // 2.episodeCount > firstUnlockEpisodeIndex
                        // 3.episodeIndex >= firstUnlockEpisodeIndex
                        // 4.当前剧集不能是下载的item
                        episodesResponse.isLockVideoAd =
                            !episodesResponse.isDownloaded && isSetLockVideoAd && episodeCount > firstUnlockEpisodeIndex && episodeIndex >= firstUnlockEpisodeIndex
                    }
                    Constants.VIDEO_CATEGORY_VARIFY -> {
                        episodesResponse.videoTitle = if (episodesResponse.title?.endsWith("期") == true) {
                            String.format("%s  %s", videoModel.name, episodesResponse.title)
                        } else {
                            String.format("%s  %s期", videoModel.name, episodesResponse.title)
                        }
                        // 第一个显示解锁广告的位置
                        val lastUnlockEpisodeIndex = videoModel.lockEps - 1
                        // 设置解锁的条件
                        // 1.isSetLockVideoAd = true
                        // 2.episodeIndex <= firstUnlockEpisodeIndex
                        // 3.当前剧集不能是下载的item
                        episodesResponse.isLockVideoAd = !episodesResponse.isDownloaded && isSetLockVideoAd && episodeIndex <= lastUnlockEpisodeIndex
                    }
                    else -> {
                        episodesResponse.videoTitle = episodesResponse.title
                        // 设置解锁的条件
                        // 1.isSetLockVideoAd = true
                        // 2.当前剧集不能是下载的item
                        episodesResponse.isLockVideoAd = isSetLockVideoAd
                    }
                }
            }
        }

        if (emptySource.isNotEmpty()) {
            emptySource.forEach {
                videoModel.sourcePlayList?.remove(it)
            }
        }
    }

    /** 获取视频推荐列表 */
    fun getVideoRecommend(genreId: Int, callback: OnRetrofitResultListener<VideoRecommendModel>) {
        val dao = NoteRoomUtils.getInstance().videoRecommendDao()
        doBaseHttp({
            val versionResponse = getVersion(Constants.API_TYPE_RELATEDRECOMMEND)
            var model: VideoRecommendModel? = null
            if (!versionResponse.isUpgrade) {
                model = withContext(Dispatchers.IO) { dao.query(genreId.toLong()) }
                if (model != null) {
                    callback.onSuccess(model)
                } else {
                    dao.delete(genreId.toLong())
                }
            }
            return@doBaseHttp model
        }, {
            val appId = getAppId()
            val timestamp = getSecondTimestamp()
            val sign = MD5Utils.getMD5String(genreId, appId, getAppKey(), timestamp, getExtra())
            val request = VideoRecommendRequest(genreId.toLong(), appId, timestamp, sign)
            return@doBaseHttp RetrofitUtils.instance.getApi(Api::class.java).getVideoRecommend(genreId, getCommonRequest(request))
        }, object : OnRetrofitResultListener<VideoRecommendModel> {

            override fun onSuccess(t: VideoRecommendModel) {
                if (isNotActive()) return
                t.genreId = genreId.toLong()
                dao.insert(t)
                callback.onSuccess(t)
            }

            override fun onFailed(msg: String) {
                if (isNotActive()) return
                callback.onFailed(msg)
            }

        })
    }


    /**  切源收藏的状态 */
    fun switchFavoriteStatus(videoId: Long): Boolean {
        val favoriteDao = NoteRoomUtils.getInstance().favoriteDao()
        val currentFavorite = videoDetailModel?.isFavorite?:false
        videoDetailModel?.isFavorite = !currentFavorite
        if (currentFavorite) { // 已经存在就删除
            favoriteDao.delete(videoId)
        } else {
            val favoriteList = favoriteDao.queryFavoriteList()
            // 最多存储100个记录
            val count = favoriteList?.size ?: 0
            if (count >= 100) {
                favoriteDao.delete(favoriteList!!.last())
            }
            val favoriteEntity = FavoriteEntity()
            favoriteEntity.videoId = videoDetailModel!!.id
            favoriteEntity.data = System.currentTimeMillis()
            favoriteEntity.name = videoDetailModel!!.name
            favoriteEntity.pic = videoDetailModel!!.pic
            favoriteEntity.actor = videoDetailModel!!.actor
            favoriteEntity.episode = currentEpisodePosition
            favoriteDao.insert(favoriteEntity)
        }
        return !currentFavorite
    }


    /**  获取当前选中的可用的视频源 */
    fun getCurrentSourceData(): PlayInfoResponse? {
        var currentSource = videoDetailModel?.sourcePlayList?.firstOrNull { it.id == currentSourceId }
        if (currentSource == null) {
            currentSource = videoDetailModel?.sourcePlayList?.firstOrNull { it.episodes?.isNotEmpty() == true }
        }
        return currentSource
    }

    fun getCurrentEpisode(): EpisodesResponse? {
        return getCurrentSourceData()?.episodes?.get(currentEpisodePosition)
    }


    /**
     * 获取是否有下载广告，包括激励和插页
     */
    fun hasDownloadAd(success: (hasAd: Boolean) -> Unit) {
        viewModelScope.launch {
            // 获取下载激励广告
            val rewardAdInfo = withContext(Dispatchers.IO) {
                AdRoomUtils.getInstance().adDao().query(AdConstants.AD_ID_DOWNLOAD_REWARD_AD)?.adInfo?.firstOrNull()
            }
            // 如果激励广告不存在，继续判断是否有插屏广告
            if (TextUtils.isEmpty(rewardAdInfo?.ad_position)) {
                val interstitialAdInfo = withContext(Dispatchers.IO) {
                    AdRoomUtils.getInstance().adDao().query(AdConstants.AD_ID_DOWNLOAD_INTERSTITIAL)?.adInfo?.firstOrNull()
                }
                success(!TextUtils.isEmpty(interstitialAdInfo?.ad_position))
            } else {
                success(true)
            }
        }
    }

    fun getDownloadTask(videoId: Long, sourceId: Int, complete: (downloadList: ArrayList<DownloadEntity>) -> Unit){
        viewModelScope.launch {
            val selection = DownloadSQLiteHelper.Columns.VIDEO_ID + "=? " +
                    "AND " +
                    DownloadSQLiteHelper.Columns.SOURCE_ID + "=?"
            val tasks = withContext(Dispatchers.IO) {
                val list = DatabaseUtils.getTasks(selection, arrayOf(videoId.toString(), sourceId.toString()))?: ArrayList()
                return@withContext ArrayList(list.sortedBy { it.episode })
            }
            if (tasks.isEmpty()) {
                complete(ArrayList())
            } else {
                complete(tasks)
            }
        }
    }

//    fun getDownloadTask(url: String, complete: (downloadList: DownloadEntity?) -> Unit){
//        if (TextUtils.isEmpty(url)) {
//            complete(null)
//            return
//        }
//        viewModelScope.launch {
//            val result = withContext(Dispatchers.IO) {
//                if (SPUtil.instance.downloadType) {
//                    NoteRoomUtils.getInstance().downloadDao().querySingle(url)
//                } else {
//                    val task = MultiDownloadManager.getTaskByUrlSync(url)
//                    DownloadViewModel.transformTask(task)
//                }
//            }
//            complete(result)
//        }
//    }

    fun getPlayStartPosition(): Long{
        currentPlayStartPosition = if (videoPlayHistoryEntity == null) {
            0
        } else {
            val target = videoPlayHistoryEntity?.episodeList?.firstOrNull { it.sourceId == currentSourceId && it.episode == currentEpisodePosition }
            target?.startPosition ?: 0
        }

        return currentPlayStartPosition
    }

    /**  取消当前剧集的解锁广告标签 */
    fun clearCurrentEpisodeUnlockAdTag() {
        videoDetailModel?.sourcePlayList?.forEach {
            it.episodes?.forEachIndexed { index, episodesResponse ->
                if (index == currentEpisodePosition && episodesResponse.isLockVideoAd) {
                    episodesResponse.isLockVideoAd = false
                    return@forEachIndexed
                }
            }
        }
    }

    /**
     * 更新播放历史记录
     */
    fun updateVideoHistory(watchingTime: Long) {
        if (watchingTime <= 0) return
        videoDetailModel?.let { video ->
            // 修改详情数据，添加历史记录
            val historyDao = NoteRoomUtils.getInstance().historyDao()
            val historyList = historyDao.queryHistories()
            // 最多存储100个记录
            historyList?.apply {
                if (this.size >= 100) {
                    historyDao.delete(last())
                }
            }
            // 不管有没有，都删除旧的内容
            historyDao.delete(video.id)
            // 新建内容
            val videoHistoryEntity = HistoryEntity()
            videoHistoryEntity.videoId = video.id
            videoHistoryEntity.data = System.currentTimeMillis()
            videoHistoryEntity.progress = watchingTime
            videoHistoryEntity.name = video.name
            videoHistoryEntity.pic = video.pic
            videoHistoryEntity.sourceId = currentSourceId
            videoHistoryEntity.episode = currentEpisodePosition
            historyDao.insert(videoHistoryEntity)


            // 新增播放记录
            val videoEpisodeEntity = VideoEpisodeEntity()
            videoEpisodeEntity.sourceId = currentSourceId
            videoEpisodeEntity.episode = currentEpisodePosition
            videoEpisodeEntity.startPosition = watchingTime
            videoEpisodeEntity.updateTime = System.currentTimeMillis()
            if (videoPlayHistoryEntity == null) {
                videoPlayHistoryEntity = VideoPlayHistoryEntity()
                videoPlayHistoryEntity?.videoId = video.id
                videoPlayHistoryEntity?.episodeList = ArrayList()
                videoPlayHistoryEntity?.episodeList?.add(videoEpisodeEntity)
            } else {
                val target = videoPlayHistoryEntity?.episodeList?.firstOrNull { it.sourceId == currentSourceId && it.episode == currentEpisodePosition }
                if (target == null) {
                    videoPlayHistoryEntity?.episodeList?.add(videoEpisodeEntity)
                } else {
                    target.startPosition = watchingTime
                    target.updateTime = System.currentTimeMillis()
                }
            }
            val videoDao = NoteRoomUtils.getInstance().videoPlayDao()
            videoDao.insert(videoPlayHistoryEntity)

//            updateDownloadVideo(watchingTime)
        }
    }


    // 获取详情所有内容
    private suspend fun getFullVideoDetail(videoId: Long) = withContext(Dispatchers.IO) {
        try {
            val appId = getAppId()
            val timestamp = getSecondTimestamp()
            val sign = MD5Utils.getMD5String(videoId, appId, getAppKey(), timestamp, getExtra())
            val request = VideoRecommendRequest(videoId, appId, timestamp, sign)
            val result = RetrofitUtils.instance.getApi(Api::class.java).getVideoDetail(videoId, getCommonRequest(request)) ?: return@withContext null
            if (result.code == 444) {
                val errorResponse = VideoEntity()
                errorResponse.code = 444
                return@withContext errorResponse
            }
            val videoDetail = checkResult(result, VideoEntity::class.java) ?: return@withContext null
            videoDetail.sourceFilePath = BaseApplication.context.getExternalFilesDir("SourceInfo")?.absolutePath + File.separator + "sourceFile_$videoId.tpt"
            // 解析视频源
            videoDetail.sourcePlayList = decodeEpisodePlayInfo(videoDetail.sourceFilePath, videoDetail.playInfo)
            // 不再需要此数据
            videoDetail.playInfo = null
            // 更新本地数据内容
            updateVideoDetailVersion(videoDetail)
            return@withContext videoDetail
        } catch (e: Exception) {
            e.printStackTrace()
            return@withContext null
        }
    }


    // 获取部分详情内容
    private suspend fun getVideoDetailPart(localVideoDetail: VideoEntity) = withContext(Dispatchers.IO) {
        try {
            val appId = getAppId()
            val timestamp = getSecondTimestamp()
            val videoId = localVideoDetail.id
            val version = localVideoDetail.version.toIntOrNull()?:0
            val sign = MD5Utils.getMD5String(videoId, version, appId, getAppKey(), timestamp, getExtra())
            val request = VideoDetailRequest(videoId, version, appId, timestamp, sign)
            val result = RetrofitUtils.instance.getApi(Api::class.java).doUpdateVodVersion(getCommonRequest(request)) ?: return@withContext null
            if (result.code == 444) {
                val errorResponse = VideoEntity()
                errorResponse.code = 444
                return@withContext errorResponse
            }
            // 获取真正的数据
            val videoVersionModel = checkResult(result, PartVideoDetailResponse::class.java) ?: return@withContext null
            if (videoVersionModel.errCode != -1) { // 需要更新
                // 更新数据
                localVideoDetail.sourcePlayList = decodeEpisodePlayInfo(localVideoDetail.sourceFilePath, videoVersionModel.data?.playInfo)
                localVideoDetail.version = videoVersionModel.vodVersion.toString()
                localVideoDetail.eps = videoVersionModel.data?.eps ?: 0
                localVideoDetail.subtitle = videoVersionModel.data?.subtitle
                localVideoDetail.update_progress = videoVersionModel.data?.update_progress
                localVideoDetail.lockEps = videoVersionModel.data?.lockEps ?: 0

                // 更新本地数据内容
                updateVideoDetailVersion(localVideoDetail)
            }
            return@withContext localVideoDetail
        } catch (e: Exception) {
            return@withContext localVideoDetail
        }
    }

    private fun <T> checkResult(resultUpgrade: CommonResponse?, clazz: Class<T>): T? {
        try {
            if (resultUpgrade?.body == null || resultUpgrade.ticket == null) {
                return null
            }
            val aesKey = EncryptionUtils.rsaDecrypt(resultUpgrade.ticket)
            val jsonBody = EncryptionUtils.aesDecrypt(resultUpgrade.body, aesKey)
            if (aesKey == null || jsonBody == null) {
                return null
            }
            return Gson().fromJson(jsonBody, clazz)
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        }
    }

    // 解密剧集信息
    private fun decodeEpisodePlayInfo(sourceFilePath: String?, playInfo: String?): ArrayList<PlayInfoResponse>? {
        if (TextUtils.isEmpty(playInfo) || sourceFilePath == null) return null
        try {
            // 解密数据
            val playInfoStr = EncryptionUtils.aesDecrypt(playInfo, AppUtils.method07())
            if (playInfoStr == null || TextUtils.isEmpty(playInfoStr)) {
                return null
            }
            // 格式化数据
            val listType = object : TypeToken<ArrayList<PlayInfoResponse>>() {}.type
            val gson = Gson()
            val result = gson.fromJson(playInfoStr, listType) as ArrayList<PlayInfoResponse>

            val file = File(sourceFilePath)
            FileUtils.createFileByDeleteOldFile(file)
            file.writeText(playInfoStr)

            return result
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        }
    }


    // 更新本地视频缓存
    private suspend fun updateVideoDetailVersion(videoDetailModel: VideoEntity) = withContext(Dispatchers.IO) {
        try {
            val dao = NoteRoomUtils.getInstance().videoEntityDao()
            val list = dao.queryAll()
            val size = list?.size ?: 0
            if (size >= 500) {
                val firstVideoId = list.first()
                val videoModel = dao.query(firstVideoId)
                if (!TextUtils.isEmpty(videoModel?.sourceFilePath)) {
                    FileUtils.delete(videoModel?.sourceFilePath)
                }
                dao.delete(firstVideoId)
            }
            dao.insert(videoDetailModel)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }


    // 此处因为异步可能会知道数据不正确，必须同步执行
    private fun isSetLockVideoAd(lockEps: Int): Boolean {
        if (lockEps <= 0) return false
        val rewardedAd = AdRoomUtils.getInstance().adDao().query(AdConstants.AD_ID_LOCK_REWARD_AD)
        return if (rewardedAd == null) {
            val interstitialAd = AdRoomUtils.getInstance().adDao().query(AdConstants.AD_ID_LOCK_INTERSTITIAL_AD)
            interstitialAd != null
        } else {
            true
        }
    }

    /**
     * 是否是剧集类型分类
     */
    fun isAlbumType(): Boolean {
        return videoDetailModel?.category != Constants.VIDEO_CATEGORY_VARIFY && videoDetailModel?.category != Constants.VIDEO_CATEGORY_MOVIE
    }

    fun release() {
        isEpisodeReverse = false
        isSetLockVideoAd = false
        videoDetailModel = null
        currentSourceId = 0
        currentEpisodePosition = 0
        currentPlayStartPosition = 0L
        videoPlayHistoryEntity = null

    }

    override fun onCleared() {
        super.onCleared()
        release()
    }


    companion object {
        const val AD_TYPE_DOWNLOAD = 1
        const val AD_TYPE_UNLOCK = 0
    }
    // 激励广告是否失败，防止多重广告出现
    private var isRewardAdFail = false
    private var rewardAdTools: CommonAdTools? = null
    private var interstitialAdTools: CommonAdTools? = null
    fun loadMultipleAd(
        activity: Activity,
        type: Int,
        loadComplete: () -> Unit
    ) {
        isRewardAdFail = false
        // 先查询是否有激励广告
        loadRewardAd(activity, type, {
            // 再次查是否有插屏广告
            loadInterstitialAd(activity, type, loadComplete)
        }, {
            loadComplete()
        })

    }


    private fun loadRewardAd(activity: Activity, type: Int, loadFail: (errorCode: Int) -> Unit, loadComplete: () -> Unit) {
        rewardAdTools = CommonAdTools()
        val rewardAdId = if (type == AD_TYPE_UNLOCK) {
            AdConstants.AD_ID_LOCK_REWARD_AD
        } else {
            AdConstants.AD_ID_DOWNLOAD_REWARD_AD
        }
        rewardAdTools?.loadAd(activity, rewardAdId, object : OnLoadAdCallback() {

            private var isUserEarnedReward = false

            override fun onAdLoaded(ad: Any?, vararg tag: Int) {
                super.onAdLoaded(ad, *tag)
                if (activity.isFinishing || activity.isDestroyed) return
                if (isRewardAdFail) return
                rewardAdTools?.showAdInActivity(activity)
            }

            override fun onAdLoadFailed(errorCode: Int) {
                super.onAdLoadFailed(errorCode)
                if (activity.isFinishing || activity.isDestroyed) return
                isRewardAdFail = true
                rewardAdTools?.release()
                loadFail(errorCode)
            }

            override fun onUserEarnedReward(amount: Int) {
                super.onUserEarnedReward(amount)
                isUserEarnedReward = true
            }

            override fun onAdComplete() {
                super.onAdComplete()
                if (activity.isFinishing || activity.isDestroyed) return
                if (isUserEarnedReward) {
                    loadComplete()
                } else {
                    loadFail(AdConstants.ERROR_CODE_AD_NO_REWARD)
                }
                rewardAdTools?.release()
            }
        })
    }


    private fun loadInterstitialAd(activity: Activity, type: Int, loadComplete: () -> Unit) {
        interstitialAdTools = CommonAdTools()
        val interstitialAdId = if (type == AD_TYPE_UNLOCK) {
            AdConstants.AD_ID_LOCK_INTERSTITIAL_AD
        } else {
            AdConstants.AD_ID_DOWNLOAD_INTERSTITIAL
        }
        interstitialAdTools?.loadAd(activity, interstitialAdId, object : OnLoadAdCallback() {

            override fun onAdLoaded(ad: Any?, vararg tag: Int) {
                super.onAdLoaded(ad, *tag)
                if (activity.isFinishing || activity.isDestroyed) return
                interstitialAdTools?.showAdInActivity(activity)
            }

            override fun onAdLoadFailed(errorCode: Int) {
                super.onAdLoadFailed(errorCode)
                if (activity.isFinishing || activity.isDestroyed) return
                loadComplete()
                interstitialAdTools?.release()
            }

            override fun onAdComplete() {
                super.onAdComplete()
                if (activity.isFinishing || activity.isDestroyed) return
                loadComplete()
                interstitialAdTools?.release()
            }

        })
    }



    fun getLocalVideoModel(videoId: Long, callback: OnRetrofitResultListener<VideoEntity>){
        viewModelScope.launch {
            try {
                val videoModel = withContext(Dispatchers.IO) {
                    val result = NoteRoomUtils.getInstance().videoEntityDao().query(videoId)
                    if (!TextUtils.isEmpty(result?.sourceFilePath)) {
                        val file = File(result.sourceFilePath)
                        if (FileUtils.isFileExists(file)) {
                            val playInfoStr = file.readText()
                            if (!TextUtils.isEmpty(playInfoStr)) {
                                // 格式化数据
                                val listType = object : TypeToken<ArrayList<PlayInfoResponse>>() {}.type
                                val gson = Gson()
                                result.sourcePlayList = gson.fromJson(playInfoStr, listType) as ArrayList<PlayInfoResponse>
                            }
                        }
                    }
                    return@withContext result
                }
                if (videoModel == null) {
                    callback.onFailed(AppUtils.getString(R.string.error_net))
                    return@launch
                }
                // 检查是否有可播放的内容
                if (videoModel.sourcePlayList.isNullOrEmpty()) {
                    callback.onFailed("1001")
                    return@launch
                }
                if (videoModel.sourcePlayList?.all { it.episodes.isNullOrEmpty() } == true) {
                    callback.onFailed("1001")
                    return@launch
                }

                // 处理视频线路
                // 线路排序要求
                // 1.置顶线路weight=9999
                // 2.推荐线路按weight排序
                // 3.剩余线路按${SPUtil.instance.videoSourceOrder}排序
                sortSourceByWeight(videoModel)

                currentSourceId = videoModel.sourcePlayList?.firstOrNull()?.id?:0

                // 处理剧集列表相关操作
                dealWithVideoEpisodeInfo(videoModel)

                this@VideoDetailViewModelNew.videoDetailModel = videoModel
                callback.onSuccess(videoModel)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

}